/******************************************************************************* * Copyright (c) 2004, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.tools.internal; import java.io.*; import java.lang.reflect.Modifier; import java.util.*; public abstract class JNIGenerator implements Flags { JNIClass mainClass; JNIClass[] classes; MetaData metaData; String delimiter; PrintStream output; ProgressMonitor progress; static final String JNI64 = "JNI64"; public JNIGenerator() { delimiter = System.getProperty("line.separator"); output = System.out; metaData = new MetaData(new Properties()); } public static String skipCopyrights(InputStream is) throws IOException { int state = 0; StringBuffer copyrights = new StringBuffer(); while (state != 5) { int c = is.read(); if (c == -1) return null; switch (state) { case 0: if (!Character.isWhitespace((char)c)) state = 1; case 1: if (c == '/') state = 2; else return null; break; case 2: if (c == '*') state = 3; else return null; break; case 3: if (c == '*') state = 4; break; case 4: if (c == '/') state = 5; else state = 3; break; } if (state > 0) copyrights.append((char)c); } return copyrights.toString(); } public static boolean compare(InputStream is1, InputStream is2) throws IOException { skipCopyrights(is1); skipCopyrights(is2); while (true) { int c1 = is1.read(); int c2 = is2.read(); if (c1 != c2) return false; if (c1 == -1) break; } return true; } public static void output(byte[] bytes, String fileName) throws IOException { FileInputStream is = null; try { is = new FileInputStream(fileName); if (compare(new ByteArrayInputStream(bytes), new BufferedInputStream(is))) return; } catch (FileNotFoundException e) { } finally { try { if (is != null) is.close(); } catch (IOException e) {} } FileOutputStream out = new FileOutputStream(fileName); out.write(bytes); out.close(); } public static String getDelimiter(String fileName) { InputStream is = null; try { is = new BufferedInputStream(new FileInputStream(fileName)); int c; while ((c = is.read()) != -1) { if (c == '\n') return "\n"; if (c == '\r') { int c1 = is.read(); if (c1 == '\n') { return "\r\n"; } else { return "\r"; } } } } catch (IOException e) { } finally { try { if (is != null) is.close(); } catch (IOException e) {} } return System.getProperty("line.separator"); } String fixDelimiter(String str) { if (delimiter.equals("\n")) return str; int index = 0, length = str.length(); StringBuffer buffer = new StringBuffer(); while (index != -1) { int start = index; index = str.indexOf('\n', start); if (index == -1) { buffer.append(str.substring(start, length)); } else { buffer.append(str.substring(start, index)); buffer.append(delimiter); index++; } } return buffer.toString(); } static String getFunctionName(JNIMethod method) { return getFunctionName(method, method.getParameterTypes()); } static String getFunctionName(JNIMethod method, JNIType[] paramTypes) { if ((method.getModifiers() & Modifier.NATIVE) == 0) return method.getName(); String function = toC(method.getName()); if (!method.isNativeUnique()) { StringBuffer buffer = new StringBuffer(); buffer.append(function); buffer.append("__"); for (int i = 0; i < paramTypes.length; i++) { JNIType paramType = paramTypes[i]; buffer.append(toC(paramType.getTypeSignature(false))); } return buffer.toString(); } return function; } static String loadFile (String file) { try { FileReader fr = new FileReader(file); BufferedReader br = new BufferedReader(fr); StringBuffer str = new StringBuffer(); char[] buffer = new char[1024]; int read; while ((read = br.read(buffer)) != -1) { str.append(buffer, 0, read); } fr.close(); return str.toString(); } catch (IOException e) { throw new RuntimeException("File not found:" + file, e); } } static void sort(JNIMethod[] methods) { Arrays.sort(methods, new Comparator<JNIMethod>() { public int compare(JNIMethod mth1, JNIMethod mth2) { int result = mth1.getName().compareTo(mth2.getName()); return result != 0 ? result : getFunctionName(mth1).compareTo(getFunctionName(mth2)); } }); } static void sort(JNIField[] fields) { Arrays.sort(fields, new Comparator<JNIField>() { public int compare(JNIField a, JNIField b) { return a.getName().compareTo(b.getName()); } }); } static void sort(JNIClass[] classes) { Arrays.sort(classes, new Comparator<JNIClass>() { public int compare(JNIClass a, JNIClass b) { return a.getName().compareTo(b.getName()); } }); } static String[] split(String str, String separator) { StringTokenizer tk = new StringTokenizer(str, separator); ArrayList<String> result = new ArrayList<String>(); while (tk.hasMoreTokens()) { result.add(tk.nextToken()); } return result.toArray(new String[result.size()]); } static String toC(String str) { int length = str.length(); StringBuffer buffer = new StringBuffer(length * 2); for (int i = 0; i < length; i++) { char c = str.charAt(i); switch (c) { case '_': buffer.append("_1"); break; case ';': buffer.append("_2"); break; case '[': buffer.append("_3"); break; case '.': buffer.append("_"); break; case '/': buffer.append("_"); break; default: buffer.append(c); } } return buffer.toString(); } public abstract void generate(JNIClass clazz); public void generateCopyright() { } public void generateIncludes() { } public void generate() { if (classes == null) return; generateCopyright(); generateIncludes(); sort(classes); for (int i = 0; i < classes.length; i++) { JNIClass clazz = classes[i]; if (getGenerate(clazz)) generate(clazz); if (progress != null) progress.step(); } output.flush(); } public void generateMetaData(String key) { MetaData mt = getMetaData(); String data = mt.getMetaData(key, null); if (data == null) return; if (data.length() == 0) return; outputln(fixDelimiter(data)); } public JNIClass[] getClasses() { return classes; } public boolean getCPP() { for (int i = 0; i < classes.length; i++) { JNIClass clazz = classes[i]; if (clazz.getFlag(FLAG_CPP)) { return true; } } return false; } public String getDelimiter() { return delimiter; } public String getExtension() { return getCPP() ? ".cpp" : getM() ? ".m" : ".c"; } public String getFileName() { return getOutputName() + getSuffix() + getExtension(); } protected boolean getGenerate(JNIItem item) { return item.getGenerate(); } public PrintStream getOutput() { return output; } public String getOutputName() { return getMainClass().getSimpleName().toLowerCase(); } public boolean getM() { for (int i = 0; i < classes.length; i++) { JNIClass clazz = classes[i]; if (clazz.getFlag(FLAG_M)) { return true; } } return false; } public JNIClass getMainClass() { return mainClass; } public MetaData getMetaData() { return metaData; } public ProgressMonitor getProgressMonitor() { return progress; } public String getSuffix() { return ""; } public void output(String str) { output.print(str); } public void outputln() { output(getDelimiter()); } public void outputln(String str) { output(str); output(getDelimiter()); } public void setClasses(JNIClass[] classes) { this.classes = classes; } public void setDelimiter(String delimiter) { this.delimiter = delimiter; } public void setMainClass(JNIClass mainClass) { this.mainClass = mainClass; } public void setMetaData(MetaData data) { metaData = data; } public void setOutput(PrintStream output) { this.output = output; } public void setProgressMonitor(ProgressMonitor progress) { this.progress = progress; } }